#include "dummyVM.h"
#include "Command_Agent.h"
#include "MappingEngine.h"
#include "WOPM.h"
#include <windows.h>
BOOL CALLBACK DialogProc( HWND, UINT, WPARAM, LPARAM);
extern HINSTANCE _hInst ;
extern HWND _hWnd ;

dummyVM::dummyVM(WOP_Entry *en, DIVA_VM *vm = NULL){
	_pointedVM = vm ;
	parent_wop = en ;
	parent_vm = NULL ;

}


dummyVM::~dummyVM(){}

void dummyVM::unfoldWOP() {
	
	WOP_Entry *objen = WOPM::getInstance()->check_existing_objects(parent_wop->getVal());
	if (objen == NULL ||
		(objen != NULL && objen->getScope() == false)) {
		// The pointed object is not yet in the WOPM
		// or the pointed object is in WOPM but scope is false.
		// initiate unfolding sequence
		// unfoldRef will create a new VM for the newly created wop_entry
		objen = Command_Agent::getInstance()->unfoldRef(parent_wop); 
		// a class object or an array object should be added into the WOPM
	    // try to retrieve its wop_entry
	}
	if( !objen ) {
		// this reference is invalid
		return;
	}
	_pointedVM = MappingEngine::getInstance()->get_vm_by_entry(objen);

	if( !this->_pointedVM ) {
		// pointee has been inline unfolded, but have no VM
		// we need to unfold again
		Command_Agent::getInstance()->unfoldObject(objen);
		assert( objen || !"invalid WOP" );
		this->_pointedVM = MappingEngine::getInstance()->get_vm_by_entry(objen);
		assert( this->_pointedVM || !"can not find pointed VM" );
	}

}

Ogre::Vector3 dummyVM::getPosition() {

	assert (parent_vm != NULL) ;  // VM programmer of reference VM should not call getPosition() in constructor

	//* story 
	// in WOP_Ref_entry, a dummy VM is first constructed
	// then a VM is constructed where dummy VM is passed as a parameter
	// at this time, dummy VM still does not know who is its parent_vm
	// so after the VM is constructed, the VM is set to parent_vm afterward
	// So, this creates a problem. In VM constructor, a VM programmer would attempt
	// to use dummy VM to getPosition(). This causes a cycle.
	// it seems the only choice is to return 0 0 0, when parent_vm is not set.
	// the parent_vm is set after VM is clicked again or valueUpdated()

	if (parent_wop->getVal() == "null") { return parent_vm->getPosition() ; }
	// when reference's value is NULL do nothing

	if (_pointedVM == NULL) {
      unfoldWOP(); // _pointedVM will be set in unfoldWOP();
	  parent_vm->VMValueUpdated();
	  // often the parent_vm is a reference VM. Originally, it is not unfolded
	  // once it is unfolded, it is equal to valueUpdated
	}
	return _pointedVM->getPosition();
}
Ogre::Vector3 dummyVM::getWorldPosition() {

	assert (parent_vm != NULL) ;  // VM programmer of reference VM should not call getWorldPosition() in constructor
	
	// in WOP_Ref_entry, a dummy VM is first constructed
	// then a VM is constructed where dummy VM is passed as a parameter
	// at this time, dummy VM still does not know who is its parent_vm
	// so after the VM is constructed, the VM is set to parent_vm afterward
	// So, this creates a problem. In VM constructor, a VM programmer would attempt
	// to use dummy VM to getPosition(). This causes a cycle.
	// it seems the only choice is to return 0 0 0, when parent_vm is not set.
	// the parent_vm is set after VM is clicked again or valueUpdated()

	if (parent_wop->getVal() == "null") { return parent_vm->getWorldPosition() ; }
	// when reference's value is NULL do nothing

	if (_pointedVM == NULL) {
		unfoldWOP();
	}
	if( !this->_pointedVM ) {
		// still fail
		return parent_vm->getWorldPosition();
	}
	return _pointedVM->getWorldPosition();
}

void dummyVM::setParentVM(DIVA_VM *vm) { parent_vm = vm ; }
DIVA_VM * dummyVM::getParentVM() { return parent_vm ; }

void dummyVM::setBodyScale(Ogre::Vector3 scale) {
	if(_pointedVM == NULL && parent_wop->getVal()!="null"){
		unfoldWOP();
		assert(_pointedVM != NULL);
		return _pointedVM->setBodyScale(scale);
	}
	_pointedVM->setBodyScale(scale);
}
bool dummyVM::isBodyScaleWrtSceneNode() { 
	assert(false); // under construction
	return true ; }

Ogre::Vector3 dummyVM::getOriginalBodySize() {
	if(_pointedVM == NULL){
		unfoldWOP();
		assert(_pointedVM != NULL);
		return _pointedVM->getOriginalBodySize();
	}
	return _pointedVM->getOriginalBodySize() ;
}

Ogre::Vector3 dummyVM::getActualSize() {
	
	if(_pointedVM == NULL){
		unfoldWOP();
		assert(_pointedVM != NULL);
		return _pointedVM->getActualSize();
	}
	return _pointedVM->getActualSize();
}
Ogre::Vector3 dummyVM::getBodyScale() {
	if(_pointedVM == NULL){
		unfoldWOP();
		assert(_pointedVM != NULL);
		return _pointedVM->getBodyScale();
	}
	return _pointedVM->getBodyScale();
}


void dummyVM::VMPicked(Ogre::Real x, Ogre::Real y, Ogre::Real z){
	if(_pointedVM == NULL){
		return;
	}
	_pointedVM->VMPicked(x,y,z);
	_pointedVM->VMSetVisible(true);  //20130129 for test
}
void dummyVM::setPosition(Ogre::Vector3 pos){
	if(_pointedVM != NULL){
		_pointedVM->setPosition(pos);
		_vm_rx_val = pos.x ;
		_vm_ry_val = pos.y ;
		_vm_rz_val = pos.z ;
	}
}

bool dummyVM::isDraggedOn(){
	
	if(_pointedVM!=NULL){
		return _pointedVM->isDraggedOn();
	}
	return true;

}

void dummyVM::VMSetVisible(bool vis){
}


